package gxprod.androidai.functions;

import java.util.Calendar;
import java.util.Date;
import java.util.Map.Entry;
import java.util.Vector;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import gxprod.androidai.AIActivity;
import gxprod.androidai.BubbleAdapter;
import gxprod.androidai.DataCollection;
import gxprod.androidai.PopupAIActivity;
import gxprod.androidai.regex.MatchResult;
import gxprod.androidai.regex.NamedPattern;
import gxprod.androidai.support.BasicEntry;
import gxprod.androidai.support.DateParsing;
import gxprod.androidai.support.DateParsing.DateMatch;
import gxprod.androidai.support.SpeekReceiver;
import gxprod.androidai.widgets.EventListWidget;

/**
 * Notes, Events, Reminders, and such
 * @author Josh Maleszewski
 */
public class OrganizationFunction extends Function {

	private final NamedPattern[] patterns = new NamedPattern[] {
			NamedPattern.compile("(make a note|note to self|(jot|write) down) (.+)"),
			NamedPattern.compile("how does my (schedule|day|morning|afternoon|week|month) look"),
			NamedPattern.compile("i (have a|need to) ([\\w ]+)"),
			
			NamedPattern.compile("remind me in ([0-9]+) (seconds|minutes|hours) (to|that i need to) ([\\w ]+)"),
			NamedPattern.compile("remind me (to|that i need to) ([\\w ]+) in ([0-9]+) (seconds|minutes|hours)"),
			
			NamedPattern.compile("when is ([\\w ]+)"),
	};

	public OrganizationFunction() {
		return;
	}

	@Override
	public MatchResult isMatch(String statement) {
		return super.isMatch(statement, patterns, 0.86f);
	}

	@Override
	public boolean execute(MatchResult match, BubbleAdapter adapter) {

		switch(match.MatchIndex) {

			case 0:
				adapter.output("I dont know how to do that yet");
				break;

			case 1:
				String timePeriod = match.Matcher.group(1);
				Date lateFilterDate = new Date();
				Date earlyFilterDate = new Date();

				if(timePeriod.equalsIgnoreCase("day") | timePeriod.equalsIgnoreCase("schedule")) {
					timePeriod = "day";
					lateFilterDate.setHours(23);
					lateFilterDate.setMinutes(59);
					lateFilterDate.setSeconds(59);

				} else if(timePeriod.equalsIgnoreCase("afternoon")) {
					lateFilterDate.setHours(23);
					lateFilterDate.setMinutes(59);
					lateFilterDate.setSeconds(59);

					earlyFilterDate.setHours(4);
					earlyFilterDate.setMinutes(0);
					earlyFilterDate.setSeconds(0);

				} else if(timePeriod.equalsIgnoreCase("morning")) {
					lateFilterDate.setHours(12);
					lateFilterDate.setMinutes(0);
					lateFilterDate.setSeconds(0);

				} else if(timePeriod.equalsIgnoreCase("week")) {
					lateFilterDate.setDate(lateFilterDate.getDate() - earlyFilterDate.getDay() + 6);

				} else if(timePeriod.equalsIgnoreCase("month")) {
					Calendar cal = Calendar.getInstance();
					cal.setTime(new Date());
					cal.add(Calendar.MONTH, 1);
					cal.set(Calendar.DAY_OF_MONTH, 1);
					cal.add(Calendar.DAY_OF_YEAR, -1);
					lateFilterDate = cal.getTime();
				}

				Vector<Event> events = getRangeOfEvents(AIActivity.get(), earlyFilterDate, lateFilterDate);

				adapter.output("you have " + events.size() + " events this " + timePeriod);
				AIActivity.get().ShowWidget(new EventListWidget(AIActivity.get(), events));
				break;


			case 2:
				String all = match.Matcher.group(2);
				String d = DateParsing.getDateContent(all);
				String description = all.replace(d, "");
				DateMatch date = DateParsing.parseDate(d);
				
				if(d.length() == 0) return false;		// 
				
				if(date != null)
					if(putEvent(AIActivity.get(), description, "", date.earliestDate, date.latestDate))
						adapter.output("I will remember");

				adapter.output("I was unable to store this event");
				break;


			case 3:
				this.reminder(match, adapter, 1, 4);
				break;
			case 4:
				this.reminder(match, adapter, 3, 2);
				break;

			default:
				return false;
		}		
		return true;
	}

	
	
	
	private void reminder(MatchResult match, BubbleAdapter adapter, int numberIndex, int taskIndex) {
		int seconds = Integer.parseInt(match.Matcher.group(numberIndex));
		String time = match.Matcher.group(numberIndex + 1);
		String title = match.Matcher.group(taskIndex);
		
		if(time.contains("minute"))
			seconds *= 60;
		if(time.contains("hour")) 
			seconds *= 3600;				
		if(time.contains("day")) 
			seconds *= 3600 * 24;
		
		StringBuilder sb = new StringBuilder();				
		sb.append("Hey, ");
		String st = (String) DataCollection.User.get(DataCollection.USER_NICNAME);
		if(st != null) {
			sb.append(st);
			sb.append(", ");
		}
		sb.append("remember you need to ");
		sb.append(title);

		putReminder(AIActivity.get(), "Reminder", title, sb.toString(), seconds);

		adapter.output("Okay. I will remind you");
	}
	
	
	@Override
	public boolean cullFunction(String statement) { return true; }

	
	public boolean putReminder(Context context, String title, String note, String speak, int secondsDelay) {

		Calendar cal = Calendar.getInstance();
		try {
			cal.setTime(new Date());
			cal.add(Calendar.SECOND, secondsDelay);

			Intent alarmintent = new Intent(context, PopupAIActivity.class);
			alarmintent.putExtra("title", title);
			alarmintent.putExtra("note", note);
			alarmintent.putExtra("say", speak);

			PendingIntent sender = PendingIntent.getActivity(context, SpeekReceiver.HELLO_ID, alarmintent, Intent.FLAG_ACTIVITY_NEW_TASK);
			AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
			am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);			
			
		} catch(Exception ex) {
			Log.e(TAG(this), "Unable to put reminder");
			ex.printStackTrace();
			return false;
		}
		Log.i(TAG(this), "Reminder sucessfully put to return at " + cal.toString());
		return true;
	}

	public boolean putEvent(Context context, String title, String description, Date begin, Date end) {

		try {
			ContentResolver cr = context.getContentResolver();
			Uri uri = Uri.parse("content://com.android.calendar/events");
			ContentValues event = new ContentValues();

			event.put("title", title);
			event.put("dtbegin", begin.getTime());
			event.put("dtend", end.getTime());

			cr.insert(uri, event);

		} catch(Exception ex) {
			Log.e(TAG(this), "Unable to put event");
			ex.printStackTrace();
			return false;
		}
		return true;		
	}

	public static Vector<Event> getRangeOfEvents(Context context, Date earlyCutOff, Date lateCutOff) {

		Vector<Event> events =  getEvents(context);

		for(int i = 0; i < events.size(); i++) {
			Event e = events.get(i);

			if(e.Begin.compareTo(earlyCutOff) < 0) {
				events.remove(i);
				i--;
			} else if(e.End.compareTo(lateCutOff) > 0) {
				events.remove(i);
				i--;
			}
		}

		return events;
	}

	public static Vector<Entry<String, String>> getCalenderIDs(Context context) {

		final Cursor cursor = context.getContentResolver().query(
				Uri.parse("content://com.android.calendar/calendars"),
				new String[] { "_id", "displayName", "selected" },
				null, null, null);

		Vector<Entry<String, String>> calenders = new Vector<Entry<String, String>>();

		while (cursor.moveToNext()) {
			final String _id = cursor.getString(0);
			final String displayName = cursor.getString(1);
			final Boolean selected = !cursor.getString(2).equals("0");

			calenders.add(new BasicEntry<String, String>(_id, displayName));

			Log.i("OrganizationFunction", "Id: " + _id + " Display Name: " + displayName + " Selected: " + selected);
		}
		cursor.close();
		return calenders;
	}

	public static Vector<Event> getEvents(Context context) {

		Vector<Event> events = new Vector<Event>();

		Uri.Builder builder = Uri.parse("content://com.android.calendar/events").buildUpon();

		Uri uri = builder.build();

		Cursor eventCursor = context.getContentResolver().query(
				uri,
				new String[] { "allDay", "title", "dtend", "dtstart" },
				null,			//"Calendars._id=" + id,
				null,
				null);

		while (eventCursor.moveToNext()) {
			Boolean allDay = !eventCursor.getString(0).equals("0");
			String title = eventCursor.getString(1);
			//String details = eventCursor.getString(2);
			Date begin = new Date(eventCursor.getLong(2));
			Date end = new Date(eventCursor.getLong(3));

			events.add(new Event(title, begin, end, allDay));

			Log.i("OrganizationFunction", "Title: " + title + " Begin: " + begin + " End: " + end + " All Day: " + allDay);
		}
		eventCursor.close();
		return events;
	}

	public static class Event {

		public Event(String name, Date begin, Date end, boolean allDay) {
			Name = name;
			Begin = begin;
			End = end;
			AllDay = allDay;
		}		
		public Event(String name, String details, Date begin, Date end, boolean allDay) {
			Name = name;
			Details = details;
			Begin = begin;
			End = end;
			AllDay = allDay;
		}		

		public String Name;
		public String Details;
		public Date Begin;
		public Date End;
		public boolean AllDay;
	}
}